package edu.amm.ui;

import edu.amm.common.StringUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * MessageBox.
 *
 * @author Иванов Илья
 * @since 2014.03.04
 */
public class MessageBox implements Initializable {

	/** Тип MessageBox'а. */
	public static enum Kind {

		INFO,

		ERROR

	}

	/** Тип кнопок MessageBox'а. */
	public static enum ButtonsType {

		OK,

		YES_NO,

		CLOSE

	}

	public static final int RETURN_CODE_ERROR = -2;
	public static final int RETURN_CODE_UNDEFINED = -1;
	public static final int RETURN_CODE_OK = 0;
	public static final int RETURN_CODE_CLOSE = 1;
	public static final int RETURN_CODE_YES = 2;
	public static final int RETURN_CODE_NO = 3;

	private static final String FXML_PATH = "MessageBox.fxml";

	private static final String INFO_TITLE = "Информация";
	private static final String ERROR_TITLE = "Ошибка!";

	private static final Color INFO_TEXT_COLOR = Color.BLACK;
	private static final Color ERROR_TEXT_COLOR = Color.RED;

	private static final Logger LOG = Logger.getLogger(MessageBox.class.getCanonicalName());

	@FXML
	private Label messageLabel;
	@FXML
	private HBox buttonsPane;

	private String message;
	private Kind kind;
	private ButtonsType buttonsType;

	private Stage stage;

	private int returnCode = RETURN_CODE_UNDEFINED;

	@Override
	public void initialize(URL url, ResourceBundle resourceBundle) {
	}

	private void initialize(String message, Kind kind, ButtonsType buttonsType, Stage stage) {
		this.message = message;
		this.kind = kind;
		this.buttonsType = buttonsType;
		this.stage = stage;

		setup();
	}

	private void setup() {
		switch (buttonsType) {
			case OK:
				Button ok = new Button("OK");
				ok.setOnAction(new EventHandler<ActionEvent>() {

					@Override
					public void handle(ActionEvent actionEvent) {
						returnCode = RETURN_CODE_OK;
						close();
					}
				});

				buttonsPane.setAlignment(Pos.CENTER);
				buttonsPane.getChildren().add(ok);

				break;

			default:
				throw new RuntimeException("MessageBox с кнопками типа " + buttonsType + " не реализован");
		}

		switch (kind) {
			case INFO:
				messageLabel.setTextFill(INFO_TEXT_COLOR);
                break;

			case ERROR:
				messageLabel.setTextFill(ERROR_TEXT_COLOR);
                break;
		}

		messageLabel.setWrapText(true);
		messageLabel.setText(message);
	}

	private void close() {
		stage.close();
	}

	public int getReturnCode() {
		return returnCode;
	}

	/**
	 * Показывет MessageBox в модальном диалоге.
	 *
	 * @param message Сообщение для показа.
	 * @param kind Тип MessageBox'а.
	 * @param buttonsType Тип кнопок MessageBox'а.
	 * @return Код возврата.
	 */
	public static int show(String message, Kind kind, ButtonsType buttonsType) {
		if (StringUtils.isNullOrEmpty(message)) {
			return RETURN_CODE_ERROR;
		}

		if (kind == null) {
			kind = Kind.INFO;
		}

		if (buttonsType == null) {
			buttonsType = ButtonsType.OK;
		}

		FXMLLoader loader;
		Parent root;
		try {
			loader = new FXMLLoader(MessageBox.class.getResource(FXML_PATH));
			root = (Parent) loader.load();
		} catch (Throwable e) {
			LOG.log(Level.SEVERE, "Невозможно показать MessageBox", e);
			return RETURN_CODE_ERROR;
		}

		Scene scene = new Scene(root);
		Stage stage = new Stage();
		stage.setScene(scene);
		stage.setResizable(false);
		stage.initModality(Modality.APPLICATION_MODAL);

		switch (kind) {
			case INFO:
				stage.setTitle(INFO_TITLE);
                break;

			case ERROR:
				stage.setTitle(ERROR_TITLE);
                break;
		}

		MessageBox controller = loader.<MessageBox>getController();
		controller.initialize(message, kind, buttonsType, stage);

		stage.show();

		return controller.getReturnCode();
	}
}
